package com.example.donghuihui.androidframe.utils;
import android.util.Log;
import com.example.donghuihui.androidframe.BuildConfig;
/**
 * Log工具类
 */
public class Logger {
    private static final char TOP_LEFT_CORNER = '╔';
    private static final char BOTTOM_LEFT_CORNER = '╚';
    private static final char MIDDLE_CORNER = '╟';
    private static final char HORIZONTAL_DOUBLE_LINE = '║';
    private static final String DOUBLE_DIVIDER = "════════════════════════════════════════════";
    private static final String SINGLE_DIVIDER = "────────────────────────────────────────────";
    private static final String TOP_BORDER = TOP_LEFT_CORNER + DOUBLE_DIVIDER + DOUBLE_DIVIDER;
    private static final String BOTTOM_BORDER = BOTTOM_LEFT_CORNER + DOUBLE_DIVIDER + DOUBLE_DIVIDER;
    private static final String MIDDLE_BORDER = MIDDLE_CORNER + SINGLE_DIVIDER + SINGLE_DIVIDER;
    public static final int LOG_FULL = 1;
    public static final int LOG_VERBOSE = Log.VERBOSE;
    public static final int LOG_DEBUG = Log.DEBUG;
    public static final int LOG_INFO = Log.INFO;
    public static final int LOG_WARN = Log.WARN;
    public static final int LOG_ERROR = Log.ERROR;
    public static final int lOG_NONE = 8;

    private static int sShowLevel = LOG_FULL;
    private static boolean sForceShow = false;

    public static void setShowLevel(int level) {
        sShowLevel = level;
    }

    public static void setForceShow(boolean forceShow) {
        sForceShow = forceShow;
    }

    public static void e(Object value) {
        if (enableShowLog()) {
            printLogBox(LOG_ERROR, getClassSimpleName(), value);
        }
    }

    public static void w(Object value) {
        if (enableShowLog()) {
            printLogBox(LOG_WARN, Constant.TAG_URL, value);
        }
    }

    public static void i(Object value) {
        if (enableShowLog()) {
            printLogBox(LOG_INFO, Constant.TAG_URL, value);
        }
    }

    public static void d(Object value) {
        if (enableShowLog()) {
            printLogBox(LOG_DEBUG, Constant.TAG_URL, value);
        }
    }

    public static void v(Object value) {
        if (enableShowLog()) {
            printLogBox(LOG_VERBOSE, Constant.TAG_URL, value);
        }
    }

    private static boolean enableShowLog() {
        return sForceShow || BuildConfig.DEBUG;
    }

    private static String getClassSimpleName() {
        String result;
        StackTraceElement methodStack = (new Exception()).getStackTrace()[2];
        result = methodStack.getClassName();
        int lastIndex = result.lastIndexOf(".");
        result = result.substring(lastIndex + 1, result.length());
        return result;
    }

    private static void printLogBox(int logLevel, String tag, Object value) {
        String valueStr;
        if(value == null){
            valueStr = "Null Object";
        } else{
            valueStr = value.toString();
        }
        printByLevel(logLevel, tag, TOP_BORDER);
        printByLevel(logLevel, tag, HORIZONTAL_DOUBLE_LINE + "Thread:" + Thread.currentThread().getName());
        printByLevel(logLevel, tag, MIDDLE_BORDER);
        printFunctionName(logLevel, tag);
        printByLevel(logLevel, tag, MIDDLE_BORDER);
        printByLevel(logLevel, tag, HORIZONTAL_DOUBLE_LINE + valueStr);
        printByLevel(logLevel, tag, BOTTOM_BORDER);
    }

    private static void printFunctionName(int logLevel, String tag) {
        StackTraceElement[] sts = Thread.currentThread().getStackTrace();
        if (sts == null) {
            return;
        }
        int lines = 0;
        for (int i = sts.length - 1; i >= 0; i--) {
            StringBuilder result = new StringBuilder();
            if (sts[i].isNativeMethod()) {
                continue;
            }
            if (sts[i].getClassName().equals(Thread.class.getName())) {
                continue;
            }
            if (sts[i].getClassName().equals(Logger.class.getName())) {
                continue;
            }
            if (sts[i].getClassName().startsWith("android")) {
                continue;
            }
            if (sts[i].getClassName().startsWith("java")) {
                continue;
            }
            if (sts[i].getClassName().startsWith("com.android")) {
                continue;
            }
            result.append(HORIZONTAL_DOUBLE_LINE);
            for (int j = 0; j < lines; j++) {
                result.append("    ");
            }
            result.append(cutOutSimpleName(sts[i].getClassName()))
                    .append(".")
                    .append(sts[i].getMethodName())
                    .append("(")
                    .append((sts[i].getFileName()))
                    .append(":")
                    .append(sts[i].getLineNumber())
                    .append(")")
                    .append("\n");
            printByLevel(logLevel, tag, result.toString());
            lines++;
        }
    }

    private static String cutOutSimpleName(String className) {
        int index = className.lastIndexOf(".");
        return className.substring(index + 1);
    }

    private static void printByLevel(int logLevel, String tag, String result) {
        if (sShowLevel <= logLevel) {
            switch (logLevel) {
                case LOG_ERROR:
                    LogUtil.e(tag, result);
                    break;
                case LOG_WARN:
                    LogUtil.w(tag, result);
                    break;
                case LOG_INFO:
                    LogUtil.i(tag, result);
                    break;
                case LOG_DEBUG:
                    LogUtil.d(tag, result);
                    break;
                case LOG_VERBOSE:
                    LogUtil.v(tag, result);
                    break;
            }
        }
    }
}
